package org.naxx.security.naxxlet.model;

import java.util.List;

import org.naxx.security.model.result.TargetEvaluationResult;

/**
 * We can optimize here for performance.
 */
public class XTarget {
	
	protected List<XAbstractMatchContainer> actionContainers; // Actions...
	protected List<XAbstractMatchContainer> environmentContainers;
	protected List<XAbstractMatchContainer> resourceContainers;
	protected List<XAbstractMatchContainer> subjectContainers;

	public final TargetEvaluationResult evaluate() {
		TargetEvaluationResult actions = this.evaluate(this.actionContainers);
		TargetEvaluationResult environments = this.evaluate(this.environmentContainers);
		TargetEvaluationResult resources = this.evaluate(this.resourceContainers);
		TargetEvaluationResult subjects = this.evaluate(this.subjectContainers);
		
		if(actions.equals(TargetEvaluationResult.INDETERMINATE)
				|| environments.equals(TargetEvaluationResult.INDETERMINATE)
				|| resources.equals(TargetEvaluationResult.INDETERMINATE)
				|| subjects.equals(TargetEvaluationResult.INDETERMINATE)) {
			return TargetEvaluationResult.INDETERMINATE;
		}
		if(actions.equals(TargetEvaluationResult.NO_MATCH)
				|| environments.equals(TargetEvaluationResult.NO_MATCH)
				|| resources.equals(TargetEvaluationResult.NO_MATCH)
				|| subjects.equals(TargetEvaluationResult.NO_MATCH)) {
			return TargetEvaluationResult.NO_MATCH;
		}
		return TargetEvaluationResult.MATCH;
	}
	
	private TargetEvaluationResult evaluate(List<XAbstractMatchContainer> xAbstractMatchContainers) {
		boolean atLeastIndeterminate = false;
		for(XAbstractMatchContainer container : xAbstractMatchContainers) {
			TargetEvaluationResult result = container.evaluate();
			if(TargetEvaluationResult.MATCH.equals(result)) {
				return TargetEvaluationResult.MATCH;
			}
			if(TargetEvaluationResult.INDETERMINATE.equals(result)) {
				atLeastIndeterminate = true;
			}
		}
		if(atLeastIndeterminate) {
			return TargetEvaluationResult.INDETERMINATE;
		}
		return TargetEvaluationResult.NO_MATCH;
	}
	
	public void addActionMatchContainer(XAbstractMatchContainer container) {
		this.actionContainers.add(container);
	}
	
	public void addEnvironmentMatchContainer(XAbstractMatchContainer container) {
		this.environmentContainers.add(container);
	}
	
	public void addResourceMatchContainer(XAbstractMatchContainer container) {
		this.resourceContainers.add(container);
	}
	
	public void addSubjectMatchContainer(XAbstractMatchContainer container) {
		this.subjectContainers.add(container);
	}
}
